This is cross-posted here from Israel.pm where I have yet to receive an answer.
I'm trying to process the directory components of a path (as an array) so that:
If the processing is to keep only the directories after "long-dir" then:
UNIX : /hello/there/long-dir/another/myfile.txt ==> another/myfile.txt DOS : C:\Hello\There\Long-Dir\Another\myfile.txt ==> another\myfile.txt UNIX: ./hi/long-dir/another/myfile.txt ==> another/myfile.txt DOS: .\hi\long-dir\another\myfile.txt ==> another\myfile.txt
To do this I turned to File::Spec and File::Basename and wrote the following code which seems insanely complicated. I marked the place where I do the actual processing using a callback:
use File::Spec;
use File::Basename;
sub _process_filename_dirs
{
my ($self, $fn, $callback) = @_;
my $basename = basename($fn);
my $dirpath = dirname($fn);
my ($volume, $directories, $filename) = File::Spec->splitpath($dirpath,
1);
# The actual manipulation.
my $dirs = $callback->([File::Spec->splitdir($directories)]);
my $final_dir =
File::Spec->catpath(
$volume, File::Spec->catdir(@$dirs), $filename
);
if ($final_dir eq "")
{
return $basename;
}
else
{
return File::Spec->catfile(
$final_dir, $basename
);
}
}
And so far I checked it works only on UNIXes (Linux in my case) and on relative paths.
So my questions are:
I should note that this hairiness is not limited to Perl. Common Lisp has a built-in portable path-manipulation abstraction that's also relatively complicated. See the "File and File I/O Chapter" and the a Portable Pathname library chapter